import { serializeVanillaModule } from './processVanillaFile';

describe('serializeVanillaModule', () => {
  test('with plain object exports', () => {
    const value = {
      string: 'value',
      boolean: true,
      number: 42,
      array: [420],
      object: { hello: 'world' },
    };

    expect(serializeVanillaModule([], value, null)).toMatchInlineSnapshot(`
      "export var string = 'value';
      export var boolean = true;
      export var number = 42;
      export var array = [420];
      export var object = {hello:'world'};"
    `);
  });

  // https://rollupjs.org/guide/en/#outputgeneratedcode -- see output.generatedCode.symbols
  // https://github.com/vitejs/vite/pull/5018
  // https://github.com/vitejs/vite/blob/757a92f1c7c4fa961ed963edd245df77382dfde6/packages/vite/src/node/build.ts#L466-L469
  test('with exports generated by Rollup', () => {
    const value = Object.freeze(
      Object.defineProperty(
        {
          __proto__: null,
          some: 'export',
        },
        Symbol.toStringTag,
        { value: 'Module' },
      ),
    );

    expect(serializeVanillaModule([], value, null)).toMatchInlineSnapshot(
      `"export var some = 'export';"`,
    );
  });

  test('with unusedCompositionRegex', () => {
    const value = {
      compositionOnly:
        'features_compositionOnly__1o6ek504 features_mergedStyle__1o6ek500 features_styleWithComposition__1o6ek501',
      mergedStyle: 'features_mergedStyle__1o6ek500',
      styleCompositionInSelector:
        'features_styleCompositionInSelector__1o6ek507 features__1o6ek505 features__1o6ek506',
      styleVariantsCompositionInSelector: {
        variant:
          'features_styleVariantsCompositionInSelector_variant__1o6ek50a features__1o6ek508 features__1o6ek509',
      },
      styleVariantsWithComposition: {
        variant:
          'features_styleVariantsWithComposition_variant__1o6ek502 features_mergedStyle__1o6ek500',
      },
      styleVariantsWithMappedComposition: {
        variant:
          'features_styleVariantsWithMappedComposition_variant__1o6ek503 features_mergedStyle__1o6ek500',
      },
      styleWithComposition:
        'features_styleWithComposition__1o6ek501 features_mergedStyle__1o6ek500',
    };

    const exports = serializeVanillaModule(
      [],
      value,
      /(features_compositionOnly__1o6ek504|features_styleCompositionInSelector__1o6ek507|features_styleVariantsCompositionInSelector_variant__1o6ek50a)\s/g,
    );
    expect(exports).toMatchInlineSnapshot(`
      "export var compositionOnly = 'features_mergedStyle__1o6ek500 features_styleWithComposition__1o6ek501';
      export var mergedStyle = 'features_mergedStyle__1o6ek500';
      export var styleCompositionInSelector = 'features__1o6ek505 features__1o6ek506';
      export var styleVariantsCompositionInSelector = {variant:'features__1o6ek508 features__1o6ek509'};
      export var styleVariantsWithComposition = {variant:'features_styleVariantsWithComposition_variant__1o6ek502 features_mergedStyle__1o6ek500'};
      export var styleVariantsWithMappedComposition = {variant:'features_styleVariantsWithMappedComposition_variant__1o6ek503 features_mergedStyle__1o6ek500'};
      export var styleWithComposition = 'features_styleWithComposition__1o6ek501 features_mergedStyle__1o6ek500';"
    `);
  });

  test('should serialize a vanilla module', () => {
    expect(
      serializeVanillaModule(
        ['import "./styles.css"'],
        { default: 'some-style', otherStyles: 'some-style other-style' },
        null,
      ),
    ).toMatchInlineSnapshot(`
      "import "./styles.css"
      var __default__ = 'some-style';
      export default __default__;
      export var otherStyles = 'some-style other-style';"
    `);
  });

  test('should re-use exports if possible', () => {
    const a = {
      style: 'the-style',
    };
    const b = {
      style: 'another-style',
    };
    const exports = {
      a,
      default: b,
      c: {
        a,
        b,
      },
    };

    expect(serializeVanillaModule(['import "./styles.css"'], exports, null))
      .toMatchInlineSnapshot(`
      "import "./styles.css"
      export var a = {style:'the-style'};
      var __default__ = {style:'another-style'};
      export default __default__;
      export var c = {a:a,b:__default__};"
    `);
  });

  test('should handle function serialization', () => {
    const sprinkles = () => {};
    sprinkles.__function_serializer__ = {
      importPath: 'my-package',
      importName: 'myFunction',
      args: ['arg1', 'arg2'],
    };
    const exports = {
      sprinkles,
    };

    expect(serializeVanillaModule(['import "./styles.css"'], exports, null))
      .toMatchInlineSnapshot(`
      "import "./styles.css"
      import { myFunction as _86bce } from 'my-package';
      export var sprinkles = _86bce('arg1','arg2');"
    `);
  });

  test('should re-use exports in handle serialized function args', () => {
    const complexExport = {
      my: {
        very: {
          complex: {
            arg: true,
          },
        },
      },
    };

    const otherComplexExport = {
      other: {
        complex: [1, 2, 3],
      },
    };

    const sprinkles = () => {};
    sprinkles.__function_serializer__ = {
      importPath: 'my-package',
      importName: 'myFunction',
      args: [complexExport, otherComplexExport],
    };
    const exports = {
      default: complexExport,
      otherComplexExport,
      sprinkles,
    };

    expect(serializeVanillaModule(['import "./styles.css"'], exports, null))
      .toMatchInlineSnapshot(`
      "import "./styles.css"
      import { myFunction as _86bce } from 'my-package';
      var __default__ = {my:{very:{complex:{arg:true}}}};
      export default __default__;
      export var otherComplexExport = {other:{complex:[1,2,3]}};
      export var sprinkles = _86bce(__default__,otherComplexExport);"
    `);
  });

  test('should order exports correctly', () => {
    const simpleObjectExport = { hello: 'world' };

    const complexExport = {
      my: {
        very: {
          complex: {
            arg: simpleObjectExport,
          },
        },
      },
    };

    const otherComplexExport = {
      other: {
        complex: [1, 2, 3],
      },
    };

    const someOtherExport = [4, 5, 6];

    const reExport = otherComplexExport;
    const reReExport = reExport;

    const sprinkles = () => {};
    sprinkles.__function_serializer__ = {
      importPath: 'my-package',
      importName: 'myFunction',
      args: [complexExport, otherComplexExport, someOtherExport, reReExport],
    };
    const exports = {
      sprinkles,
      complexExport,
      simpleObjectExport,
      reReExport,
      otherComplexExport,
      default: someOtherExport,
      reExport,
    };

    expect(serializeVanillaModule(['import "./styles.css"'], exports, null))
      .toMatchInlineSnapshot(`
      "import "./styles.css"
      import { myFunction as _86bce } from 'my-package';
      export var simpleObjectExport = {hello:'world'};
      export var complexExport = {my:{very:{complex:{arg:simpleObjectExport}}}};
      var __default__ = [4,5,6];
      export default __default__;
      export var reExport = {other:{complex:[1,2,3]}};
      export var sprinkles = _86bce(complexExport,reExport,__default__,reExport);
      export var reReExport = reExport;
      export var otherComplexExport = reExport;"
    `);
  });
});
